/*
 * @Description: 好友模块
 * @Author: Yong
 * @Date: 2021-09-29 21:27:42
 * @LastEditTime: 2021-10-10 21:18:34
 */
import { Provide, MidwayFrameworkType, App } from "@midwayjs/decorator"
import { InjectEntityModel } from "@midwayjs/orm"
import { Application as SocketApplication } from '@midwayjs/socketio';
import { Repository } from "typeorm"
import { Friends, User, Messages } from '../entity/index.entity'
import { AFO } from "../interface"
import { Context } from "@midwayjs/koa"
import { Inject } from "@midwayjs/decorator"
import { resHandler } from "../utils"
import { MessageService } from "./Message"

@Provide()
export class FriendsService {

    @Inject()
    ctx: Context

    @App(MidwayFrameworkType.WS_IO)
    socketApp: SocketApplication;

    @Inject()
    messageService: MessageService

    // 好友表实体
    @InjectEntityModel(Friends)
    friendsModel: Repository<Friends>

    // 一对一消息表实体
    @InjectEntityModel(Messages)
    MessagesModel: Repository<Messages>

    // 用户表实体
    @InjectEntityModel(User)
    UserModel: Repository<User>

    // 申请添加好友
    async applyFriends (applyFriends: AFO) {
        try {
            // 判断是否已经申请 - 好友表是否已经存在当前对象
            const friends = await this.friendsModel.findOne({ where: { F_FriendID: applyFriends.U_FriendID, F_UserID: applyFriends.U_UserID } })
            if (friends) {
                // 存在说明已申请过好友 - 只做修改最新时间操作
                await this.updateLastTimeBy(applyFriends.U_UserID, applyFriends.U_FriendID)
            } else {
                // 不存在 - 好友表插入两条数据
                await this.addFriends(applyFriends.U_UserID, applyFriends.U_FriendID, 1)
                await this.addFriends(applyFriends.U_FriendID, applyFriends.U_UserID, 2)
            }
            // 插入申请好友消息
            await this.messageService.addMessage({
                uid: applyFriends.U_UserID,
                fid: applyFriends.U_FriendID,
                cont: `请求添加好友-${new Date().getTime()}`,
                type: 0,
                state: 1,
            })
            // 获取好友申请个数
            const applyFriendTotal = (await this.getFriends(applyFriends.U_FriendID.toString(), 2)).total
            // 通知首页对方好友客户端更新好友申请个数
            this.socketApp.of('/home').emit('updateApplyFriendTotal', { applyFriendTotal: applyFriendTotal, toId: applyFriends.U_FriendID })
            // 返回前端数据
            this.ctx.body = resHandler.successRes()
        } catch (e) {
            console.log(e)
            this.ctx.body = resHandler.errorRes()
        }
    }

    // 好友表 - 添加好友申请数据
    async addFriends (uid: string, fid: string, state: number) {
        const friends = new Friends()
        friends.F_UserID = uid
        friends.F_FriendID = fid
        friends.F_FriendStatus = state
        friends.F_LastTime = new Date()
        await this.friendsModel.save(friends)
    }

    // 好友表 - 更新最新时间
    async updateLastTimeBy (uid: string, fid: string) {
        await this.friendsModel.createQueryBuilder()
            .update(Friends)
            .set({ F_LastTime: new Date() })
            .where({ F_FriendID: fid, F_UserID: uid })
            .orWhere({ F_FriendID: uid, F_UserID: fid })
            .execute()
    }

    // 同意好友申请 - F_FriendStatus = 0
    async updateFriendStates (updateFriendObj: AFO) {
        try {
            // 更新Friends状态
            await this.friendsModel.createQueryBuilder()
                .update(Friends)
                .set({ F_FriendStatus: 0 })
                .where('F_UserID = :F_UserID And F_FriendID= :F_FriendID', { F_UserID: updateFriendObj.U_UserID, F_FriendID: updateFriendObj.U_FriendID })
                .orWhere('F_UserID = :F_FriendID And F_FriendID= :F_UserID', { F_UserID: updateFriendObj.U_UserID, F_FriendID: updateFriendObj.U_FriendID })
                .execute()
            // 插入同意好友申请消息
            await this.messageService.addMessage({
                uid: updateFriendObj.U_UserID,
                fid: updateFriendObj.U_FriendID,
                cont: `我们已经是好友，一起来聊天吧！-${new Date().getTime()}`,
                type: 0,
                state: 1,
            })
            
            // 更新好友的home端 - 好友消息列表
            const friendMsgList = (await this.getFriends(updateFriendObj.U_FriendID, 0))
            this.socketApp.of('/home').emit('updateFriendMsgList', { friendMsgList: friendMsgList, toId: updateFriendObj.U_FriendID })

            // 响应前端
            this.ctx.body = resHandler.successRes()
        } catch (error) {
            this.ctx.body = resHandler.errorRes()
        }
    }

    // 拒绝好友申请 - 删除好友表记录
    async delFriends (delFriendObj: AFO) {
        try {
            await this.friendsModel.createQueryBuilder()
                .delete()
                .from(Friends)
                .where('F_UserID = :F_UserID And F_FriendID= :F_FriendID', { F_UserID: delFriendObj.U_UserID, F_FriendID: delFriendObj.U_FriendID })
                .orWhere('F_UserID = :F_FriendID And F_FriendID= :F_UserID', { F_UserID: delFriendObj.U_UserID, F_FriendID: delFriendObj.U_FriendID })
                .execute()
            this.ctx.body = resHandler.successRes()
        } catch (error) {
            this.ctx.body = resHandler.errorRes()
        }
    }

    // 获取好友申请列表 - 用户ID/申请状态为2
    async getApplyFriendsList (uid: string) {
        this.ctx.body = resHandler.successRes((await this.getFriends(uid, 2)).list)
    }

    // 联表查询 - state = 2 获取好友申请个数 state = 0 获取好友消息列表
    async getFriends (uid: string, state: number) {
        // 联表查询 - User/Friends
        const FriendList = await this.friendsModel.createQueryBuilder()
            .where({ F_UserID: uid, F_FriendStatus: state })
            .leftJoinAndSelect(User, 'user', 'F_FriendID = user.ID')
            .orderBy('friends.F_LastTime', 'DESC')
            .select(`
                user.ID as id,
                user.U_LoginID as nickName,
                user.U_Avatar as avatar,
                friends.F_LastTime as lastTime
            `)
            .getRawMany()
        // 获取-最新的消息/以及未读信息数
        const returnData = []
        for (let i = 0; i < FriendList.length; i++) {
            const currentItem = FriendList[i]
            const messageItem = await this.messageService.getLastMessage(currentItem.id, uid)
            const unreadMsgCount = await this.messageService.getUnreadMsgCount(currentItem.id, uid)
            returnData.push({ ...currentItem, msgCon: messageItem.M_Cont, unreadCount: unreadMsgCount })
        }
        return {
            total: returnData.length,
            list: returnData
        }
    }

}
